using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Data;
using Microsoft.ApplicationBlocks.Data;
using System.Collections;
using System.IO;
using System.Xml;

namespace Microsoft.SharedSource.SqlServer.MDDE.Repository
{
    public sealed class MDDEPackage
    {
        #region Fields

        MDDEPackageTemplate parentTemplate;
        string name;
        string version;
        string body;
        XmlDocument changesFromTemplate;

        #endregion

        #region Properties

        public string Version
        {
            get { return version; }
            set { this.version = value; }
        }

        public string Body
        {
            get
            {
                if (body == null)
                {
                    // Get the package body.
                    SqlParameter[] spParams = new SqlParameter[2];
                    spParams[0] =
                        new SqlParameter("@templateId",
                        this.ParentTemplate.Id);
                    spParams[1] =
                        new SqlParameter("@packageName", this.Name);

                    body = SqlHelper.ExecuteScalar(
                        this.ParentTemplate.
                        ParentRepository.RepositoryConnection,
                        CommandType.Text,
                        Resource.GetPackageBody, spParams).ToString();
                }
                return body;
            }
            set { body = value; }
        }

        public XmlDocument ChangesFromTemplate
        {
            get { return changesFromTemplate; }
            set { changesFromTemplate = value; }
        }

        public MDDEPackageTemplate ParentTemplate
        {
            get { return parentTemplate; }
        }

        public string Name
        {
            get { return name; }
            set { this.name = value; }
        }

        #endregion

        #region Methods

        public MDDEPackage(MDDEPackageTemplate parentTemplate, string packageName)
        {
            // Set the parent property.
            this.parentTemplate = parentTemplate;

            // Fill in the basic package info.
            this.name = packageName;

            // Get package information.
            SqlParameter[] spParams = new SqlParameter[2];
            spParams[0] =
                new SqlParameter("@templateId", this.ParentTemplate.Id);
            spParams[1] =
                new SqlParameter("@packageName", this.Name);

            DataSet packageInfo =
                SqlHelper.ExecuteDataset(
                this.parentTemplate.
                ParentRepository.RepositoryConnection,
                CommandType.Text,
                Resource.GetPackageInfo, spParams);

            // Return if no package found.
            if (packageInfo.Tables[0].Rows.Count == 0)
                return;

            DataRow r = packageInfo.Tables[0].Rows[0];

            this.version = r["PackageVersion"].ToString();

            if (r["ChangesFromTemplate"] != DBNull.Value)
            {
                this.changesFromTemplate = new XmlDocument();
                this.changesFromTemplate.
                    LoadXml(r["ChangesFromTemplate"].ToString());
            }
        }

        public void Create()
        {
            SqlParameter[] spParams = new SqlParameter[5];
            spParams[0] =
                new SqlParameter("@packageName", this.Name);
            spParams[1] =
                new SqlParameter("@packageVersion", this.Version);
            spParams[2] =
                new SqlParameter("@templateID", this.parentTemplate.Id);
            spParams[3] =
                new SqlParameter("@packageBody", this.Body);
            spParams[4] =
                new SqlParameter(
                "@changesFromTemplate",
                this.ChangesFromTemplate.InnerXml);

            // Create a new package.
            Convert.ToInt32(SqlHelper.ExecuteScalar(
                this.parentTemplate.
                ParentRepository.RepositoryConnection,
                CommandType.StoredProcedure,
                "sp_CreatePackage", spParams));

            this.parentTemplate.RefreshPackages();
        }

        public void Delete()
        {
            // Delete package.
            SqlParameter[] spParams = new SqlParameter[2];
            spParams[0] =
                new SqlParameter("@templateId", this.ParentTemplate.Id);
            spParams[1] =
                new SqlParameter("@packageName", this.Name);

            SqlHelper.ExecuteScalar(
                this.parentTemplate.
                ParentRepository.RepositoryConnection,
                CommandType.StoredProcedure,
                "sp_DeletePackage", spParams);

            this.parentTemplate.RefreshPackages();
        }

        public void Update()
        {
            SqlParameter[] spParams = new SqlParameter[5];
            spParams[0] = new SqlParameter(
                "@templateId", this.parentTemplate.Id);
            spParams[1] = new SqlParameter(
                "@packageName", this.Name);
            spParams[2] = new SqlParameter(
                "@packageVersion", this.Version);
            spParams[3] = new SqlParameter(
                "@packageBody", this.Body);
            spParams[4] = new SqlParameter(
                "@changesFromTemplate", this.ChangesFromTemplate.InnerXml);

            // Update the package.
            SqlHelper.ExecuteScalar(
                this.parentTemplate.
                ParentRepository.RepositoryConnection,
                CommandType.StoredProcedure,
                "sp_UpdatePackage", spParams);
        }

        private void RefreshBody()
        {
            this.body = null;
        }

        #endregion
    }

    public sealed class PackageCollection : IEnumerable
    {
        #region Fields

        private Dictionary<string, MDDEPackage> packages =
            new Dictionary<string, MDDEPackage>();

        #endregion

        #region Properties

        public MDDEPackage this[string packageName]
        {
            get { return packages[packageName]; }
        }

        public int Count
        {
            get
            {
                return packages.Count;
            }
        }

        #endregion

        #region Methods

        public void Add(MDDEPackage tin)
        {
            packages.Add(tin.Name, tin);
        }

        public void Remove(string packageName)
        {
            packages.Remove(packageName);
        }

        public bool ContainsPackage(string packageName)
        {
            return packages.ContainsKey(packageName);
        }

        internal void Clear()
        {
            this.packages.Clear();
        }

        #endregion

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return packages.Values.GetEnumerator();
        }

        #endregion
    }
}
